// import { ASSERT_NUMBER_EQ, ASSERT_FLOAT_EQ, ASSERT_TRUE, ASSERT_FALSE, ASSERT_EQ } from "../../../utils/assert";
// import { BenchmarkRunner } from "../../../utils/benchmarkTsSuite";
declare function print(arg:any) : string;
// Modify n value to change the difficulty of the benchmark
// suggesting using input = 5500;

declare interface ArkTools{
	timeInUs(arg:any):number
}


const input: number = 500;

function approximate(u: Float64Array, v: Float64Array, buffer: Float64Array): number {
    for (let count = 0; count < 10; count++) {
        multiplyAv(u, buffer);
        multiplyAtv(buffer, v);

        multiplyAv(v, buffer);
        multiplyAtv(buffer, u);
    }

    let vLen: number = v.length;
    let vBv: number = 0.0, vv: number = 0.0;
    for (let i = 0; i < vLen; i++) {
        vBv += u[i] * v[i];
        vv += v[i] * v[i];
    }

    return Math.sqrt(vBv / vv);
}

function multiplyAv(v: Float64Array, av: Float64Array): void {
    let vLen = v.length;
    let avLen = av.length;
    for (let i = 0; i < avLen; i++) {
        av[i] = 0.0;
        for (let j = 0; j < vLen; j++) {
            const ij = i + j;
            let ret = 1.0 / (ij * (ij + 1) / 2 + i + 1);
            av[i] +=ret * v[j];
        }
    }
}

function multiplyAtv(v: Float64Array, atv: Float64Array): void {
    let vLen = v.length;
    let atvLen = atv.length;
    for (let i = 0; i < atvLen; i++) {
        atv[i] = 0;
        for (let j = 0; j < vLen; j++) {
            const ij = i + j;
            let ret = 1.0 / (ij * (ij + 1) / 2 + j + 1);
            atv[i] += ret * v[j];
        }
    }
}

function RunSpectralNorm() {
    const n: number = input;
    const u: number[] = Array(n).fill(1.0);
    const v: number[] = Array(n).fill(0.0);
    const buffer: number[] = Array(n).fill(0.0);
    let uF: Float64Array = new Float64Array(u);
    let vF: Float64Array = new Float64Array(v);
    let bufferF: Float64Array = new Float64Array(buffer);
    let res = 0.0;
    const start = ArkTools.timeInUs();
    res = approximate(uF, vF, bufferF);
    const end = ArkTools.timeInUs();
    // ASSERT_FLOAT_EQ(res, 1.2742241159529055);
    let time = (end - start) / 1000
    print("Array Access - RunSpectralNorm:\t"+String(time)+"\tms");
	return time;
}
RunSpectralNorm()
// let runner = new BenchmarkRunner("Array Access - RunSpectralNorm", RunSpectralNorm);
// runner.run();
